<!--
 * @Descripttion: 
 * @Author: jhw
 * @Date: 2024-06-25 14:31:23
 * @LastEditors: jhw
 * @LastEditTime: 2024-06-27 15:47:07
-->
<template>
  <div class="FormClass">
    <el-form
      ref="ruleFormRef"
      :rules="rules"
      label-width="auto"
      class="demo-ruleForm"
      status-icon
      :model="model"
      v-bind="$attrs"
    >
      <el-row>
        <template v-for="item in props.list" :key="item.prop">
          <el-col v-bind="item.grid || girdConfig.grid">
            <el-form-item
              :label="item.label"
              :prop="item.prop"
              :label-width="item.labelWidth || formItemConfig.labelWidth"
              :class="item.fieldType === 'checkbox' ? 'checkbox-form-item' : ''"
            >
              <template v-if="item.fieldType === 'input'">
                <el-input
                  v-model="model[item.prop]"
                  :placeholder="`请输入${item.label}`"
                  clearable
                  v-bind="item.otherProps"
                />
              </template>
              <template v-else-if="item.fieldType === 'select'">
                <el-select
                  v-model="model[item.prop]"
                  :placeholder="`请选择${item.label}`"
                  clearable
                  v-bind="item.otherProps"
                >
                  <el-option
                    v-for="(option, index) in item.extra ? props.dict[item.extra] : item.options"
                    :key="index"
                    :label="option.label"
                    :value="option.value"
                  />
                </el-select>
              </template>
              <!-- select2会有滚动条警告，尽量不用 -->
              <template v-else-if="item.fieldType === 'select2'">
                <el-select-v2
                  v-model="model[item.prop]"
                  :placeholder="`请选择${item.label}`"
                  :clearable="true"
                  :props="{ label: 'label', value: 'value' }"
                  :options="item.extra ? [...props.dict[item.extra]] : [...item.options as any[]]"
                  v-bind="item.otherProps"
                />
              </template>
              <template v-else-if="item.fieldType === 'datepicker'">
                <el-date-picker
                  v-model="model[item.prop]"
                  :placeholder="`请选择${item.label}`"
                  clearable
                  v-bind="item.otherProps"
                />
              </template>
              <template v-else-if="item.fieldType === 'timepicker'">
                <el-time-picker
                  v-model="model[item.prop]"
                  :placeholder="`请选择${item.label}`"
                  clearable
                  v-bind="item.otherProps"
                />
              </template>

              <template v-else-if="item.fieldType === 'cascader'">
                <el-cascader
                  v-model="model[item.prop]"
                  :options="item.extra ? props.dict[item.extra] : item.options"
                  :placeholder="`请选择${item.label}`"
                  clearable
                  v-bind="item.otherProps"
                  @change="item.callback"
                />
              </template>

              <template v-else-if="item.fieldType === 'radio'">
                <el-radio-group v-model="model[item.prop]">
                  <el-radio
                    v-for="option in item.extra ? props.dict[item.extra] : item.options"
                    :key="option.value"
                    :value="option.value"
                    >{{ option.label }}</el-radio
                  >
                </el-radio-group>
              </template>

              <template v-else-if="item.fieldType === 'rate'">
                <el-rate v-model="model[item.prop]" v-bind="item.otherProps" />
              </template>

              <!-- slider也会有滚动条警告，尽量不用 -->
              <template v-else-if="item.fieldType === 'slider'">
                <el-slider v-model="model[item.prop]" v-bind="item.otherProps" />
              </template>

              <template v-else-if="item.fieldType === 'switch'">
                <el-switch v-model="model[item.prop]" v-bind="item.otherProps" />
              </template>

              <template v-else-if="item.fieldType === 'treeselect'">
                <el-tree-select
                  v-model="model[item.prop]"
                  :data="item.extra ? props.dict[item.extra] : item.options"
                  :placeholder="`请选择${item.label}`"
                  clearable
                  v-bind="item.otherProps"
                />
              </template>

              <template v-else-if="item.fieldType === 'checkbox'">
                <el-checkbox
                  v-if="item.isShowCheckAll"
                  v-model="item.checkAll"
                  :indeterminate="item.isIndeterminate"
                  @change="
                    () => {
                      model[item.prop] = item.checkAll
                        ? ((item.extra ? props.dict[item.extra] : item.options) || []).map((item) => item.value)
                        : [];
                    }
                  "
                >
                  全选
                </el-checkbox>
                <el-checkbox-group v-model="model[item.prop]" @change="handleCheckChange(item)">
                  <el-checkbox
                    v-for="checkItem in item.extra ? props.dict[item.extra] : item.options"
                    :key="checkItem.value"
                    :label="checkItem.label"
                    :value="checkItem.value"
                  >
                    {{ checkItem.label }}
                  </el-checkbox>
                </el-checkbox-group>
              </template>

              <!-- colorpicker有滚动条警告，尽量不用 -->
              <template v-else-if="item.fieldType === 'color'">
                <el-color-picker v-model="model[item.prop]" v-bind="item.otherProps" />
              </template>

              <template v-else>
                <slot :name="item.slot" :data="item"></slot>
              </template>
            </el-form-item>
          </el-col>
        </template>
      </el-row>
    </el-form>
  </div>
</template>

<script setup lang="ts">
import { PropType, computed, ref } from 'vue';
import { IListPropsType, dictPropsType } from './config';
import type { FormInstance } from 'element-plus';

const props = defineProps({
  modelValue: {
    type: Object,
    required: true,
  },
  list: {
    type: Array as PropType<IListPropsType>,
    required: true,
  },
  dict: {
    type: Object as PropType<dictPropsType>,
    required: false,
    default: () => {},
  },
  rules: {
    type: Object,
    required: false,
    default: () => ({}),
  },
  girdConfig: {
    type: Object,
    default: () => {
      return {
        grid: {
          xs: 24,
          sm: 24,
          md: 24,
          lg: 24,
          xl: 24,
        },
        gutter: 20,
      };
    },
  },
  formItemConfig: {
    type: Object,
    default: () => {
      return {
        labelWidth: '90px',
        labelPosition: 'right',
        labelSuffix: '',
        size: 'medium',
      };
    },
  },
});

const emit = defineEmits(['update:modelValue']);

const ruleFormRef = ref<FormInstance>();

const model = computed({
  get() {
    return new Proxy(props.modelValue, {
      set(target, key, value) {
        // console.log(1111, { target, key, value });
        emit('update:modelValue', { ...target, [key]: value });
        return true;
      },
    });
  },
  set(val) {
    emit('update:modelValue', val);
  },
});

const validateForm = async () => {
  try {
    const res = await ruleFormRef.value?.validate();
    return res;
  } catch (error) {
    return false;
  }
};

// 重置
const onReset = () => {
  if (!ruleFormRef.value) return;
  ruleFormRef.value.resetFields();
};

// 处理checkbox全选
const handleCheckChange = (item: any) => {
  item.checkAll = model.value[item.prop].length === ((item.extra ? props.dict[item.extra] : item.options) || []).length;
  item.isIndeterminate =
    model.value[item.prop].length > 0 &&
    model.value[item.prop].length < ((item.extra ? props.dict[item.extra] : item.options) || []).length;
  item.callback && item.callback([...model.value[item.prop]]);
};

// 去除el-select滚动条警告，有待优化
// onMounted(() => {
//   const selectElement = document.querySelector('.el-select');
//   if (selectElement) {
//     console.log('selectElement', selectElement);

//     selectElement.addEventListener('wheel', () => {}, { passive: true });
//   }
// });
defineExpose({
  validateForm,
  onReset,
  handleCheckChange,
});
</script>

<style lang="scss" scoped>
.FormClass {
  :deep(.el-form) {
    .el-input,
    .el-select,
    .el-date-picker,
    .el-select-v2,
    .el-date-editor,
    .el-cascader {
      width: 100%;
    }

    .checkbox-form-item {
      .el-form-item__content {
        display: flex;
        flex-direction: column;
        align-items: start;
      }
    }
  }
}
</style>
